#include "gwbase/base/atomic.h"
#include "gwbase/base/test_harness.h"
#include "gwbase/base/thread.h"
#include <boost/bind.hpp>

class AtomicTest {
 public:
  void Reset() { val_.Store_Release(0); }

  void AddVal(int32_t n) {
    for (int32_t i = 0; i < n; ++i) val_.Increment();
  }

 protected:
  dicom::AtomicInt32 val_;
};

TEST(AtomicTest, SingleThread) {
  Reset();
  AddVal(1000);
  EXPECT_Eq(val_.Load_Acquire(), 1000);
}

TEST(AtomicTest, TwoThread) {
  Reset();
  const int32_t kCount = 100000;
  dicom::ThreadPtr t1(
      new dicom::Thread(boost::bind(&AtomicTest::AddVal, this, kCount), "t1"));
  dicom::ThreadPtr t2(
      new dicom::Thread(boost::bind(&AtomicTest::AddVal, this, kCount), "t2"));

  t1->Start();
  t2->Start();

  t1->Join();
  t2->Join();

  EXPECT_Eq(val_.Load_Acquire(), kCount * 2);
}

int main() {
  dicom::RunAllTests();
  return 0;
}
